<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<title>Document</title>
		<style>
			svg {
				cursor: all-scroll;
				border: solid 1px red;
			}
			
			.centralText {
				font: 23spx sans-serif;
				fill: #222;
			}
			
			.downwardNode text,
			.upwardNode text {
				font: 10px sans-serif;
			}
			
			.downwardLink {
				fill: none;
				stroke: #8b4513;
				stroke-width: 1px;
				opacity: 0.5;
			}
			
			.upwardLink {
				fill: none;
				stroke: #37592b;
				stroke-width: 1px;
				opacity: 0.5;
			}
		</style>
	</head>

	<body>
		<div id="downLond">123</div>
		<div id="box"></div>

		<script src="./d3/d3.js" type="text/javascript" charset="utf-8"></script>
		<!-- <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> -->
		<script type="text/javascript" src="./data.json"></script>
		<script>
			// const down = document.getElementById('downLond');
			// down.onclick = function(){
			// 	var _this = this;
			// 	var html = document.getElementsByTagName('html')[0]; //获取可视区域宽
   //  		var g = document.getElementsByTagName('g')[0].getBBox()
			// 	var gbox = document.getElementsByClassName('gbox')[0];
			// 	var x = -g.x;//计算偏移位置
			// 	var y = -g.y;
			// 	// g.y < 0 ? y = Math.abs(g.y) : y = 0
			// 	// gbox.style.transform = "translate(" + x + 'px' + "," + (y-60) + "px" + ")  scale(1)"; //偏移位置
			// 	gbox.style.transform = "translate(" + x + 'px' + "," + y + "px" + ")  scale(1)"; //偏移位置
			// 	var svgbox = $('#box svg')
			// 	var boxwidth = svgbox.width;
			// 	var boxheight = svgbox.height;
			// 	svgbox.attr('width', g.width)
			// 	svgbox.attr('height', g.height)
			// 	var canvas = document.createElement("canvas");
			// 	var c = canvas.getContext('2d');
			// 	//新建Image对象
			// 	//svg内容
			// 	var svg = document.getElementById('box').innerHTML;

			// 	var img = new Image();
				
			// 	img.src = 'data:image/svg+xml,' + unescape(encodeURIComponent(svg));//svg内容中可以有中文字符
			// 	img.src = 'data:image/svg+xml,' + svg;//svg内容中不能有中文字符
			// 	img.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg)));//svg内容中可以有中文字符

			// 	//图片初始化完成后调用
			// 	 img.onload = function() {
			// 		//将canvas的宽高设置为图像的宽高
			// 		canvas.width = img.width;
			// 		canvas.height = img.height+60;
			// 		c.fillStyle = "#fff";
			// 		c.fillRect(0, 0, canvas.width, canvas.height);
			// 		c.drawImage(img, 0, 30);
			// 		//canvas画图片

			// 		var a = document.createElement("a");
			// 		a.download = "png";
			// 		a.href= canvas.toDataURL("image/png");
			// 		a.click();
			// 	}
			// 	//图片转换为base64后 传给后端 发邮件	
			// 	gbox.style.transform = ''
			// 	svgbox.attr('width',boxwidth)
			// 	svgbox.attr('height',boxheight)
			// }

			var rootName = ''; //根节点的名字
			var rootRectWidth = 0; //根节点rect的宽度
			var downwardLength = 0,
				upwardLength = 0;
			var forUpward = true

			var treeChart = function(d3Object) {
				this.d3 = d3Object;
				this.directions = ['upward', 'downward'];
			};


			treeChart.prototype.drawChart = function() {
				// First get tree data for both directions.
				this.treeData = {};
				var self = this;
				d3.json('./data.json', function(error, allData) {
					// console.log(allData)
					self.directions.forEach(function(direction) {
						// console.log(direction)
						self.treeData[direction] = allData[direction];
					});
					rootName = '上海冰鉴信息科技有限公司';
					rootRectWidth = rootName.length * 15;
					//获得upward第一级节点的个数
					upwardLength = allData.upward.children.length;
					//获得downward第一级节点的个数
					downwardLength = allData.downward.children.length;
					self.graphTree(self.getTreeConfig());
				});
			};

			treeChart.prototype.getTreeConfig = function() {
				var treeConfig = {
					'margin': {
						'top': 10,
						'right': 5,
						'bottom': 0,
						'left': 30
					}
				}

				treeConfig.chartWidth = (1400 - treeConfig.margin.right - treeConfig.margin.left);
				treeConfig.chartHeight = (800 - treeConfig.margin.top - treeConfig.margin.bottom);
				treeConfig.centralHeight = treeConfig.chartHeight / 2;
				treeConfig.centralWidth = treeConfig.chartWidth / 2;
				treeConfig.linkLength = 120;
				treeConfig.duration = 500; //动画时间
				return treeConfig;
			};

			treeChart.prototype.graphTree = function(config) {
				var self = this;
				var d3 = this.d3;
				var linkLength = config.linkLength;
				var duration = config.duration;
				var hasChildNodeArr = [];
				var id = 0;
				
					
				var diagonal = d3.svg.diagonal()
					.source(function(d) {
						// console.log(d)
						return {
							"x": d.source.x,
							"y": d.source.name == 'origin' ? (forUpward ? d.source.y -20 :d.source.y + 20) : (forUpward ? d.source.y - 60 : d.source.y + 60)
						};
					})
					.target(function(d) {
						return {
							"x": d.target.x,
							"y": d.target.y
						};
					})
					.projection(function(d) {
						return [d.x, d.y];
					});	
				
				var zoom = d3.behavior.zoom()
					.scaleExtent([0.5, 2])
					.on('zoom', redraw);
				var svg = d3.select('#box')
					.append('svg')
					.attr('xmlns', 'http://www.w3.org/2000/svg')
					.attr('width', config.chartWidth + config.margin.right + config.margin.left)
					.attr('height', config.chartHeight + config.margin.top + config.margin.bottom)
					.on('mousedown', disableRightClick)
					.call(zoom)
					.on('dblclick.zoom', null);
				var treeG = svg.append('g').attr('class','gbox')
					.attr('transform', 'translate(' + config.margin.left + ',' + config.margin.top + ')');

				//箭头(下半部分)
				var markerDown = svg.append("marker")
					.attr("id", "resolvedDown")
					.attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
					.attr("markerUnits", "userSpaceOnUse")
					.attr("viewBox", "0 -5 10 10") //坐标系的区域
					.attr("refX", 0) //箭头坐标
					.attr("refY", 0)
					.attr("markerWidth", 12) //标识的大小
					.attr("markerHeight", 12)
					.attr("orient", "90") //绘制方向，可设定为：auto（自动确认方向）和 角度值
					.attr("stroke-width", 2) //箭头宽度
					.append("path")
					.attr("d", "M0,-5L10,0L0,5") //箭头的路径
					.attr('fill', '#000'); //箭头颜色  
				//箭头(上半部分)
				var markerUp = svg.append("marker")
					.attr("id", "resolvedUp")
					.attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
					.attr("markerUnits", "userSpaceOnUse")
					.attr("viewBox", "0 -5 10 10") //坐标系的区域
					.attr("refX", 10) //箭头坐标
					.attr("refY", 0)
					.attr("markerWidth", 12) //标识的大小
					.attr("markerHeight", 12)
					.attr("orient", "90") //绘制方向，可设定为：auto（自动确认方向）和 角度值
					.attr("stroke-width", 2) //箭头宽度
					.append("path")
					.attr("d", "M0,-5L10,0L0,5") //箭头的路径
					.attr('fill', '#000'); //箭头颜色  

				// Initialize the tree nodes and update chart.
				for(var d in this.directions) {
					var direction = this.directions[d];
					var data = self.treeData[direction];
					data.x0 = config.centralWidth;
					data.y0 = config.centralHeight;
					data.children.forEach(collapse);
					update(data, data, treeG);
				}

				function update(source, originalData, g) {
					// console.log(source)
					var direction = originalData['direction'];
					forUpward = direction == 'upward';
					var node_class = direction + 'Node';
					var link_class = direction + 'Link';
					var downwardSign = (forUpward) ? -1 : 1;
					var nodeColor = (forUpward) ? '#37592b' : '#8b4513';

					var isExpand = false;
					var statusUp = true;
					var statusDown = true;
					var nodeSpace = 130;
					var tree = d3.layout.tree().sort(sortByDate).nodeSize([nodeSpace, 0]);
					var nodes = tree.nodes(originalData);
					var links = tree.links(nodes);
					var offsetX = -config.centralWidth;
					nodes.forEach(function(d) {
						d.y = downwardSign * (d.depth * linkLength) + config.centralHeight;
						d.x = d.x - offsetX;
						if(d.name == 'origin') {
							d.x = config.centralWidth;
							d.y += downwardSign * 0; // 上下两树图根节点之间的距离
						}
					});

					// Update the node.
					var node = g.selectAll('g.' + node_class)
						.data(nodes, function(d) {
							return d.id || (d.id = ++id);
						});
					var nodeEnter = node.enter().append('g')
						.attr('class', node_class)
						.attr('transform', function(d) {
							return 'translate(' + source.x0 + ',' + source.y0 + ')';
						})
						.style('cursor', function(d) {
							return(d.name == 'origin') ? '' : (d.children || d._children) ? 'pointer' : '';
						})
						.on('click', click);

					nodeEnter.append("svg:rect")
						.attr("x", function(d) {
							return(d.name == 'origin') ? -(rootRectWidth / 2) : -60;
						})
						.attr("y", function(d) {
							return(d.name == 'origin') ? -20 : forUpward ? -52 : 12;
						})
						.attr("width", function(d) {
							return(d.name == 'origin') ? rootRectWidth : 120;
						})
						.attr("height", 40)
						.attr("rx", 10)
						.style("stroke", function(d) {
							return(d.name == 'origin') ? "#1078AF" : "#CCC";
						})
						.style("fill", function(d) {
							return(d.name == 'origin') ? "#0080E3" : "#FFF";   //节点背景色
						});

					nodeEnter.append('circle')
						.attr('r', 1e-6);
					nodeEnter.append("text")
						.attr("class", "linkname")
						.attr("x", function(d) {
							return(d.name == 'origin') ? '0' : "-55";
						})
						.attr('dy', function(d) {
							return(d.name == 'origin') ? '.35em' : forUpward ? '-40' : '24';
						})
						.attr("text-anchor", function(d) {
							return(d.name == 'origin') ? 'middle' : "start";
						})
						.attr('fill', '#000')
						.text(function(d) {
							if(d.name == 'origin') {
								// return ((forUpward) ? '根节点TOP' : '根节点Bottom');
								return rootName;
							} 
							if(d.repeated) {
								return '[Recurring] ' + d.name;
							}
							return(d.name.length > 10) ? d.name.substr(0, 10) : d.name;
						})
						.style({
							'fill-opacity': 1e-6,
							'fill': function(d) {
								if(d.name == 'origin') {
									return '#fff';
								}
							},
							'font-size': function(d) {
								return(d.name == 'origin') ? 14 : 11;
							},
							'cursor': "pointer"
						})
						.on('click', function() {
							alert(1);
						});

					nodeEnter.append("text")
						.attr("class", "linkname")
						.attr("x", "-55")
						.attr("dy", function(d) {
							return(d.name == 'origin') ? '.35em' : forUpward ? '-29' : '35';
						})
						.attr("text-anchor", function() {
							return(d.name == 'origin') ? 'middle' : "start";
						})
						.text(function(d) {
							return d.name.substr(10, d.name.length);
						})
						.style({
							'fill': "#337ab7",
							'font-size': function(d) {
								return(d.name == 'origin') ? 14 : 11;
							},
							'cursor': "pointer"
						})
						.on('click', function() {
							alert(1);
						});;

					nodeEnter.append("text")
						.attr("x", "-55")
						.attr("dy", function(d) {
							return(d.name == 'origin') ? '.35em' : forUpward ? '-16' : '48';
						})
						.attr("text-anchor", "start")
						.attr("class", "linkname")
						.style("fill", "#fff")
						.style('font-size', 10)
						.text(function(d) {
							var str = (d.name == 'origin') ? '' : "认缴金额:1000万人民币";
							return(str.length > 13) ? str.substr(0, 13) + ".." : str;
						});
					nodeEnter.append("text")
						.attr("x", "10")
						.attr("dy", function(d) {
							return(d.name == 'origin') ? '.35em' : forUpward ? '0' : '10';
						})
						.attr("text-anchor", "start")
						.attr("class", "linkname")
						.style("fill", "green")
						.style('font-size', 10)
						.text(function(d) {
							return(d.name == 'origin') ? "" : "66.66%";
						});

					// Transition nodes to their new position.原有节点更新到新位置
					var nodeUpdate = node.transition()
						.duration(duration)
						.attr('transform', function(d) {
							return 'translate(' + d.x + ',' + d.y + ')';
						});
					nodeUpdate.select('circle')
						.attr('r', function(d) {
							return(d.name == 'origin') ? 0 : (hasChildNodeArr.indexOf(d) == -1) ? 0 : 6;
						})
						.attr('cy', function(d) {
							return(d.name == 'origin') ? -20 : (forUpward) ? -59 : 59;
						})
						.style('fill', function(d) {
							return hasChildNodeArr.indexOf(d) != -1 ? "#fff" : "";
							// if (d._children || d.children) { return "#fff"; } else { return "rgba(0,0,0,0)"; }
						})
						.style('stroke', function(d) {
							return hasChildNodeArr.indexOf(d) != -1 ? "#8b4513" : "";
							// if (d._children || d.children) { return "#8b4513"; } else { return "rgba(0,0,0,0)"; }
						})
						.style('fill-opacity', function(d) {
							if(d.children) {
								return 0.35;
							}
						})
						// Setting summary node style as class as mass style setting is
						// not compatible to circles.
						.style('stroke-width', function(d) {
							if(d.repeated) {
								return 5;
							}
						});
					//代表是否展开的+-号
					nodeEnter.append("svg:text")
						.attr("class", "isExpand")
						.attr("x", "0")
						.attr("dy", function(d) {
							return forUpward ? -56 : 62;
						})
						.attr("text-anchor", "middle")
						.style("fill", "#000")
						.text(function(d) {
							if(d.name == 'origin') {
								return '';
							}
							return hasChildNodeArr.indexOf(d) != -1 ? "+" : "";
							/* if (d._children || d.children) {
								return "+";
							} */
						});

					nodeUpdate.select('text').style('fill-opacity', 1)

					//******************************************最终受益人 start******************************************//
					//提示框
					var tsk = nodeEnter.append("svg:rect")
						.attr("x", -60)
						.attr("y", function(d) {
							return forUpward ? -86 : -20;
						})
						.attr("width", function(d) {
							if(d.name == 'origin') {
								return 0
							} else {
								return d.hasHumanholding ? 120 : 0; //如果有最终受益人
							}
						})
						.attr("height", 20)
						.style("stroke", function(d) {
							return "#1078AF";
						})
						.style("fill", function(d) {
							return "#46A2D2";
						})
					//三角形
					nodeEnter.append("svg:path")
						.attr("fill", "#1078AF")
						.attr("d", function(d) {
							if(d.name == 'origin') {
								return ""
							} else {
								return d.hasHumanholding ? (forUpward ? "M-60 -66 L-40 -66 L-50 -52 Z" : "M-60 0 L-40 0 L-50 12 Z") : ""; //如果有最终受益人
							}
						})
					nodeEnter.append("svg:text")
						.attr("x", "-58")
						.attr("dy", function(d) {
							return forUpward ? "-73" : "-7";
						})
						.attr("text-anchor", "start")
						.style("fill", "#fff")
						.style("font-size", 10)
						.text(function(d) {
							var str = ("我是最终受益人").length > 6 ? ("我是最终受益人").substr(0, 6) + ".." : ("我是最终受益人");
							return d.hasHumanholding ? "最终受益人:" + str : ""; //如果有最终受益人
						});
					//******************************************最终受益人 end******************************************//

					
					var nodeExit = node.exit().transition()
						.duration(duration)
						.attr('transform', function(d) {
							return 'translate(' + source.x + ',' + source.y + ')';
						})
						.remove();
					nodeExit.select('circle')
						.attr('r', 1e-6)
					nodeExit.select('text')
						.style('fill-opacity', 1e-6);

					var link = g.selectAll('path.' + link_class)
						.data(links, function(d) {
							return d.target.id;
						});

					link.enter().insert('path', 'g')
						.attr('class', link_class)
						.attr('stroke',function(d){
							return '#000000'
						})
						.attr('fill',"none")
						.attr('stroke-width',0.5)
						.attr('d', function(d) {
							var o = {
								x: source.x0,
								y: source.y0
							};
							return diagonal({
								source: o,
								target: o
							});
						})
						.attr("marker-end", function(d) {
							return forUpward ? "url(#resolvedUp)" : "url(#resolvedDown)";
						}) //根据箭头标记的id号标记箭头;
						.attr("id", function(d, i) {
							return "mypath" + i;
						})
					link.transition()
						.duration(duration)
						.attr('d', diagonal);
					link.exit().transition()
						.duration(duration)
						.attr('d', function(d) {
							var o = {
								x: source.x,
								y: source.y
							};
							return diagonal({
								source: o,
								target: o
							});
						})
						.remove();
					nodes.forEach(function(d) {
						d.x0 = d.x;
						d.y0 = d.y;
					});

					function click(d) {
						if(forUpward) {
							if(d._children) {
								console.log('股东--ok')
							} else {
								console.log('股东--no')
							}
						} else {
							if(d._children) {
								console.log('对外投资--ok')
							} else {
								console.log('对外投资--no')
							}
						}

						isExpand = !isExpand;
						if(isExpand) {
							d3.select(this).select(".isExpand").text("-")
						} else {
							d3.select(this).select(".isExpand").text("+")
						}

						if(d.name == 'origin') {
							return;
						}
						if(d.children) {
							d._children = d.children;
							d.children = null;
						} else {
							d.children = d._children;
							d._children = null;
							// expand all if it's the first node
							if(d.name == 'origin') {
								d.children.forEach(expand);
							}
						}
						update(d, originalData, g);
					}
				}

				function expand(d) {
					if(d._children) {
						d.children = d._children;
						d.children.forEach(expand);
						d._children = null;
					}
				}


				function collapse(d) {
					if(d.children && d.children.length != 0) {
						d._children = d.children;
						d._children.forEach(collapse);
						d.children = null;
						hasChildNodeArr.push(d);
					}
				}


				function redraw() {
					treeG.attr('transform', 'translate(' + d3.event.translate + ')' +
						' scale(' + d3.event.scale + ')');
				}

				function disableRightClick() {
					// stop zoom
					if(d3.event.button == 2) {
						console.log('No right click allowed');
						d3.event.stopImmediatePropagation();
					}
				}


				function sortByDate(a, b) {
					var aNum = a.name.substr(a.name.lastIndexOf('(') + 1, 4);
					var bNum = b.name.substr(b.name.lastIndexOf('(') + 1, 4);
					return d3.ascending(aNum, bNum) ||
						d3.ascending(a.name, b.name) ||
						d3.ascending(a.id, b.id);
				}
			};

			var d3GenerationChart = new treeChart(d3);
			d3GenerationChart.drawChart();
		</script>
	</body>

</html>